/**
  * Author: Mei
  * Date: 2020-12-10 10:09
  * Description: 
  * decltype关键字 找出表达式的类型  和typeof类似
  *
  */
#include <vector>
#include <iostream>
#include <string>
#include <bitset>
#include <functional>
#include <algorithm>
#include <list>
#include <set>
#include <map>

using namespace std;

//第一种用处 用在返回值上面
//template<typename T1, typename T2>
//decltype(x + y) add(T1 x, T2 y) { //编译不通过 'x' was not declared in this scope
//
//};

//修改
template<typename T1, typename T2>
auto add1(T1 x, T2 y) -> decltype(x + y) { //尾托 指明返回值类型

};

//第二种用处 metaprogramming  源编程(在模板中的运用)
template<typename T>
void test18_decltype(T obj) {
    map<string, float>::value_type elem1; //为pair<>类型

    map<string, float> coll;
    decltype(coll)::value_type
    elem2;


    //可以这么使用
    typedef typename decltype(obj)
    ::iterator iType;
    //还可以
    typedef typename T::iterator iType2;

    decltype(obj) anotherObj(obj); //复制对象
}

//第三种用处  用在lambda表达式上面
class Persons {
private:
    string last, first;
public:
    Persons(string la, string fi) : last(la), first(fi) {}

    string lastname() const {
        return last;
    }
    //自定义比较器
    bool operator<(const Persons &p1) const {
        return true;
    }
    string firstname() const {
        return first;
    }

};

auto cmp = [](const Persons &p1, const Persons &p2) {
    return p1.lastname() < p2.lastname() ||
           (p1.lastname() == p2.lastname() &&
            p1.firstname() > p2.firstname());
};

bool cmp1(const Persons &p1, const Persons &p2) {
    return p1.lastname() < p2.lastname() ||
           (p1.lastname() == p2.lastname() &&
            p1.firstname() > p2.firstname());
}

struct Students
{
    string id;
    int age,height;
    Students(string s,int a,int h):id(s),age(a),height(h){}
    Students() {}
};

bool cmp2(const Students &s1,const Students &s2){
    if(s1.id!=s2.id) return s1.id<s2.id;
    return s1.age<s2.age;
}

int main() {
    map<string, string> coll;
    //elem为const类型
    decltype(coll)::value_type
    elem = make_pair<string, string>("li", "si");
    cout << elem.first << "," << elem.second << endl;

    decltype(2.3) a = 20;
    cout << a << endl;

    //如果没有使用co(cmp)的构造函数 编译失败 则直接使用编译器默认的比较器
    set<Persons, decltype(cmp)> co(cmp); //decltype(cmp)为指针类型
    Persons p("a2a", "bb");
    Persons p1("1aa", "bb");
    Persons p2("2aa", "bb");
    co.insert(p);
    co.insert(p1);
    co.insert(p2);
    for(auto c : co) {
        cout << c.firstname()<<", "<<c.lastname()<<endl;
    }



    return 0;
}
